package com.rc.evcharger.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Sven on 2021/08/28
 */
public class JWTUtil {
    //密钥文本，密钥不要泄漏
    //生成签名的时候使用的秘钥secret,这个方法本地封装了的，一般可以从本地配置文件中读取，切记这个秘钥不能外露哦。
    // 它就是你服务端的私钥，在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了

    /**
     * 创建一个带有uid字段的token，过期时间为3分钟
     */
    public static String generateToken(String tenantCode, String secret) {
        //JWT默认头部alg=HS256，typ=JWT，如果不更换加密方式可以不设置头部
        Map<String, Object> header = new HashMap();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        String token = JWT.create() //创建一个jwt对象
                .withHeader(header) //设置Header（头部）
                .withExpiresAt(new Date(System.currentTimeMillis() + 3L * 60 * 1000))  //设置过期时间为3分钟后，因此生成的JWT只在3分钟内能通过验证
                //.withJWTId(UUID.randomUUID().toString())//设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                .withClaim("tenantCode", tenantCode)  //创建payload的私有声明（根据特定的业务需要添加，如果要拿这个做验证，一般是需要和jwt的接收方提前沟通好验证方式的）,多个字段在后面继续使用withClaim()方法即可
                .sign(Algorithm.HMAC256(secret));   //设置签名，签名算法为头部的HS256，密钥为secret变量的值
        return token;
    }

    /**
     * 解密token,JJWT并没有提供判断JWT是否合法的方法，但是在解码非法JWT时会抛出异常，因此可以通过捕获异常的方式来判断是否合法
     */
    public static DecodedJWT decoded(String secret, String token) throws Exception {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();//创建一个加密算法为HS256的校验器
        DecodedJWT decoded = verifier.verify(token); //校验传入的token，生成一个解密的JWT
        return decoded;
    }

    public static void main(String[] args) throws Exception {
        String secret = "914401153";

        System.out.println("当前时间：" + new Date());
        String token = generateToken("914401153", secret);
        System.out.println("token：" + token);

        //String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsImV4cCI6MTU5ODU4Mjk1NX0.ddG7I9GQQ2l52oLxt47RRuYl3DmMxpGvHfO9RxPhtfE";
        DecodedJWT decoded = decoded(secret, token);
        System.out.println("过期时间：" + decoded.getExpiresAt());
        System.out.println("tenantCode:" + decoded.getClaim("tenantCode").asString());
    }
}
